import CryptoJS from 'crypto-js'

export default class XfyunIat {
  constructor(options = {}) {
    // 配置参数
    this.appId = 'c2b5d65b'
    this.apiKey =   '2858613b805d3d6687c69f67d7cee395'
    this.apiSecret =   'NmNjMGM2OWQzMWM3N2EyZjA4MTFiN2Uw'
    
    // 状态管理
    this.socketTask = null
    this.recorderManager = null
    this.socketState = 'closed' // connecting | connected | closing | closed | error
    this.connectPromise = null
    this.reconnectAttempts = 0
    this.maxReconnectAttempts = 3
    
    // 音频配置
    this.audioConfig = {
      sampleRate: 16000,
      frameSize: 1280,
      format: 'PCM'
    }
    
    // 回调函数
    this.callbacks = {
      onTextChange: () => {},
      onError: () => {},
      onComplete: () => {},
      onStatusChange: () => {}
    }
  }

  // 生成WebSocket连接URL
  getWebSocketUrl() {
    const host = 'iat-api.xfyun.cn'
    const date = new Date().toGMTString()
    const algorithm = 'hmac-sha256'
    const headers = 'host date request-line'
    
    const signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v2/iat HTTP/1.1`
    const signatureSha = CryptoJS.HmacSHA256(signatureOrigin, this.apiSecret)
    const signature = CryptoJS.enc.Base64.stringify(signatureSha)
    
    const authorization = `api_key="${this.apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`
    
    return `wss://${host}/v2/iat?authorization=${encodeURIComponent(authorization)}&date=${encodeURIComponent(date)}&host=${encodeURIComponent(host)}`
  }

  // 初始化WebSocket连接（带自动重连）
  async initWebSocket() {
    if (this.socketState === 'connected') return
    if (this.socketState === 'connecting') return this.connectPromise
    
    this._updateStatus('connecting')
    
    this.connectPromise = new Promise((resolve, reject) => {
      const url = this.getWebSocketUrl()
      
      this.socketTask = uni.connectSocket({
        url: url,
        complete: () => {
          // 微信小程序需要手动监听事件
          this.socketTask.onOpen(() => {
            this.reconnectAttempts = 0
            this._updateStatus('connected')
            resolve()
          })
          
          this.socketTask.onMessage((res) => {
            if (this.socketState !== 'connected') return
            this._handleMessage(res.data)
          })
          
          this.socketTask.onError((err) => {
            this._handleError(new Error(`WebSocket错误: ${err.errMsg}`))
            reject(err)
          })
          
          this.socketTask.onClose(() => {
            if (this.socketState !== 'closing') {
              this._handleError(new Error('WebSocket意外关闭'))
            }
            this._updateStatus('closed')
          })
        }
      })
    })
    
    // 添加8秒超时控制
    const timeoutPromise = new Promise((_, reject) => {
      setTimeout(() => {
        reject(new Error('WebSocket连接超时'))
      }, 8000)
    })
    
    try {
      await Promise.race([this.connectPromise, timeoutPromise])
    } catch (err) {
      this._handleError(err)
      throw err
    }
    
    return this.connectPromise
  }

  // 初始化录音管理器
  initRecorder() {
    this.recorderManager = wx.getRecorderManager()
    
    this.recorderManager.onStart(() => {
      console.log('录音开始')
    })
    
    this.recorderManager.onStop(() => {
      console.log('录音停止')
    })
    
    this.recorderManager.onError((err) => {
      this._handleError(new Error(`录音错误: ${err.errMsg}`))
    })
    
    this.recorderManager.onFrameRecorded((res) => {
      if (res.frameBuffer && this.socketState === 'connected') {
        this._sendAudioData(res.frameBuffer, res.isLastFrame)
      }
    })
  }

  // 开始语音识别
  async start() {
    try {
      // 确保WebSocket连接
      await this.initWebSocket()
      
      // 初始化录音
      if (!this.recorderManager) {
        this.initRecorder()
      }
      
      // 发送开始参数
      this._sendStartParams()
      
      // 开始录音
      this.recorderManager.start({
        format: this.audioConfig.format,
        sampleRate: this.audioConfig.sampleRate,
        numberOfChannels: 1,
        frameSize: this.audioConfig.frameSize,
        encodeBitRate: this.audioConfig.sampleRate,
        frameBufferType: 'arraybuffer'
      })
      
    } catch (err) {
      this._handleError(err)
      throw err
    }
  }

  // 停止语音识别
  async stop() {
    if (this.socketState === 'closed' || this.socketState === 'error') return
    
    try {
      // 先停止录音
      if (this.recorderManager) {
        this.recorderManager.stop()
      }
      
      // 标记正在关闭
      this._updateStatus('closing')
      
      // 关闭WebSocket
      if (this.socketTask) {
        await new Promise((resolve) => {
          this.socketTask.close({
            success: resolve,
            fail: resolve // 即使失败也继续
          })
        })
      }
      
    } catch (err) {
      console.warn('停止过程中出错:', err)
    } finally {
      this._updateStatus('closed')
    }
  }

  // 发送开始参数
  _sendStartParams() {
    const startData = {
      "common": {
        "app_id": this.appId
      },
      "business": {
        "language": "zh_cn",
        "domain": "iat",
        "accent": "mandarin",
        "dwa": "wpgs",
        "pd": "game"
      },
      "data": {
        "status": 0,
        "format": `audio/L16;rate=${this.audioConfig.sampleRate}`,
        "encoding": "raw",
        "audio": ""
      }
    }
    
    this.socketTask.send({
      data: JSON.stringify(startData)
    })
  }

  // 发送音频数据
  _sendAudioData(buffer, isLastFrame = false) {
    const audioData = {
      "data": {
        "status": isLastFrame ? 2 : 1,
        "format": `audio/L16;rate=${this.audioConfig.sampleRate}`,
        "encoding": "raw",
        "audio": this._arrayBufferToBase64(buffer)
      }
    }
    
    this.socketTask.send({
      data: JSON.stringify(audioData)
    })
  }

  // 处理服务器返回的消息
  _handleMessage(data) {
    try {
      const result = JSON.parse(data)
      if (result.code !== 0) {
        this._handleError(result)
        return
      }
      
      const text = this._decodeResult(result.data)
      if (text) {
        const isEnd = result.data.result && result.data.result.ls
        this.callbacks.onTextChange(text, isEnd)
        
        if (isEnd) {
          this.callbacks.onComplete(text)
        }
      }
    } catch (e) {
      this._handleError(new Error(`消息解析失败: ${e.message}`))
    }
  }

  // 解码识别结果
  _decodeResult(data) {
    if (!data || !data.result) return ''
    
    let result = ''
    data.result.ws.forEach((item) => {
      item.cw.forEach((cw) => {
        result += cw.w
      })
    })
    
    return result
  }

  // ArrayBuffer转Base64
  _arrayBufferToBase64(buffer) {
    const bytes = new Uint8Array(buffer)
    let binary = ''
    for (let i = 0; i < bytes.byteLength; i++) {
      binary += String.fromCharCode(bytes[i])
    }
    return btoa(binary)
  }

  // 错误处理
  _handleError(err) {
    console.error('语音识别错误:', err)
    this.callbacks.onError(err)
    this._updateStatus('error')
    
    // 自动重连逻辑
    if (this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++
      setTimeout(() => {
        if (this.socketState === 'error') {
          this.initWebSocket().catch(() => {})
        }
      }, 2000 * this.reconnectAttempts)
    }
  }

  // 更新状态
  _updateStatus(status) {
    this.socketState = status
    this.callbacks.onStatusChange(status)
  }

  // 注册回调函数
  onTextChange(callback) {
    this.callbacks.onTextChange = callback
  }
  
  onError(callback) {
    this.callbacks.onError = callback
  }
  
  onComplete(callback) {
    this.callbacks.onComplete = callback
  }
  
  onStatusChange(callback) {
    this.callbacks.onStatusChange = callback
  }
}